package edu.ccut.saturn.studio.validate.dialog;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.wizards.TypedElementSelectionValidator;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.views.navigator.ResourceSorter;

import edu.ccut.saturn.studio.Activator;
import edu.ccut.saturn.studio.Images;
import edu.ccut.saturn.studio.core.util.eclipse.Messages;
import edu.ccut.saturn.studio.core.util.eclipse.SaturnProjectUtil;
import edu.ccut.saturn.studio.core.util.eclipse.SaturnSWTUtils;
import edu.ccut.saturn.studio.core.util.eclipse.SaturnValidation;
import edu.ccut.saturn.studio.core.util.file.FileFilter;
import edu.ccut.saturn.studio.core.util.freemaker.FreemarkerUtils;
//import edu.ccut.saturn.studio.validate.wizard.Messages;

/**
 * 
 * @author Bai Yucheng 2007-12-6
 * 
 */
public class CreateClassDialog extends TitleAreaDialog {
	private Text classNameText;
	private Text pkgText;
	private Text srcText;
	private Shell shell;

	private String wokSpacePath;
	private String projectName;
	private String srcName;
	private String pkgName;
	private String className;
	private IProject project;

	/**
	 * Create the dialog
	 * 
	 * @param parentShell
	 */
	public CreateClassDialog(Shell parentShell, IProject project, String pkgName) {
		super(parentShell);
		this.shell = parentShell;
		this.projectName = project.getName();
		this.srcName = "src"; //$NON-NLS-1$
		this.pkgName = pkgName;
		this.project = project;
	}

	/**
	 * Create contents of the dialog
	 * 
	 * @param parent
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		Composite area = (Composite) super.createDialogArea(parent);
		Composite container = new Composite(area, SWT.NONE);
		final GridLayout gridLayout = new GridLayout();
		gridLayout.marginWidth = 4;
		gridLayout.marginRight = 5;
		gridLayout.marginLeft = 5;
		gridLayout.marginTop = 5;
		gridLayout.numColumns = 3;
		container.setLayout(gridLayout);
		container.setLayoutData(new GridData(GridData.FILL_BOTH));

		final Label srcLabel = new Label(container, SWT.NONE);
		srcLabel.setText(Messages.getString("CreateClassDialog.srcfile")); //$NON-NLS-1$

		srcText = new Text(container, SWT.BORDER | SWT.READ_ONLY);
		srcText.setTextLimit(100);
		final GridData gd_srcText = new GridData(SWT.FILL, SWT.CENTER, true,
				false);
		srcText.setLayoutData(gd_srcText);
		if (projectName.equals("")) { //$NON-NLS-1$
			srcText.setText(""); //$NON-NLS-1$
		} else {
			srcText.setText(projectName + "/" + srcName); //$NON-NLS-1$
		}
		srcText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});

		final Button srcBrowerButton = new Button(container, SWT.NONE);
		srcBrowerButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				IPath[] paths = CreateClassDialog.chooseFileEntries(shell,
						null, new IPath[0], Messages.getString("CreateClassDialog.choosesrcfile"), Messages.getString("CreateClassDialog.chooseonesrcfile"), //$NON-NLS-1$ //$NON-NLS-2$
						new String[] { "" }, false, true, false); //$NON-NLS-1$
				if (paths != null && paths.length == 1) {
					String name = (String) (paths[0]).toOSString();
					name = name.substring(1, name.length()).replace("\\", "/"); //$NON-NLS-1$ //$NON-NLS-2$
					srcText.setText(name);
				}
			}
		});
		srcBrowerButton.setText(Messages.getString("CreateClassDialog.browsing")); //$NON-NLS-1$

		final Label pkgLabel = new Label(container, SWT.NONE);
		pkgLabel.setText(Messages.getString("CreateClassDialog.packagename")); //$NON-NLS-1$

		pkgText = new Text(container, SWT.BORDER | SWT.READ_ONLY);
		pkgText.setTextLimit(100);
		final GridData gd_pkgText = new GridData(SWT.FILL, SWT.CENTER, true,
				false);
		pkgText.setLayoutData(gd_pkgText);
		if (pkgName.equals("")) { //$NON-NLS-1$
			pkgText.setText(""); //$NON-NLS-1$
		} else {
			pkgText.setText(formatPkgName(pkgName));
		}
		pkgText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});

		final Button pkgBrowerButton = new Button(container, SWT.NONE);
		pkgBrowerButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(final SelectionEvent e) {
				String str = srcText.getText();
				IPath path = new Path(str);
				IWorkspaceRoot fWorkspaceRoot = ResourcesPlugin.getWorkspace()
						.getRoot();
				IResource res = fWorkspaceRoot.findMember(path);
				IProject proj = res.getProject();
				IJavaProject jproject = JavaCore.create(proj);
				IPackageFragmentRoot fCurrRoot = jproject
						.getPackageFragmentRoot(res);
				try {
					IJavaElement[] javaElementsTemp = fCurrRoot.getChildren();
					IJavaElement[] javaElements = new IJavaElement[javaElementsTemp.length - 1];
					for (int i = 1; i < javaElementsTemp.length; i++) {
						javaElements[i - 1] = javaElementsTemp[i];
					}
					ElementListSelectionDialog dialog = new ElementListSelectionDialog(
							shell,
							new SaturnSWTUtils.SaturnLabelDefaultProvider() {
								public Image getImage(Object element) {
									return Activator
											.getImage(Images.DATABASE_TABLE_FOLDER);
								}

								public String getText(Object element) {
									IPackageFragment ipack = (IPackageFragment) element;
									return ipack.getElementName();
								}
							});
					dialog.setTitle(Messages.getString("CreateClassDialog.choosepackage")); //$NON-NLS-1$
					dialog.setMessage(Messages.getString("CreateClassDialog.pleasechooseonepackage")); //$NON-NLS-1$
					dialog.setElements(javaElements);
					if (dialog.open() == Window.OK) {
						pkgText
								.setText(((IJavaElement) dialog
										.getFirstResult()).getElementName());
					}
				} catch (JavaModelException e1) {
					e1.printStackTrace();
				}
			}
		});
		pkgBrowerButton.setText(Messages.getString("CreateClassDialog.browsing")); //$NON-NLS-1$

		final Label classNameLabel = new Label(container, SWT.NONE);
		classNameLabel.setText(Messages.getString("CreateClassDialog.classname")); //$NON-NLS-1$

		classNameText = new Text(container, SWT.BORDER);
		classNameText.setTextLimit(50);
		final GridData gd_classNameText = new GridData(SWT.FILL, SWT.CENTER,
				true, false);
		classNameText.setLayoutData(gd_classNameText);
		classNameText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				dialogChanged();
			}
		});

		new Label(container, SWT.NONE);
		setTitle(Messages.getString("CreateClassDialog.createvalidateclass")); //$NON-NLS-1$
		setMessage(Messages.getString("CreateClassDialog.createvalidatejavaclass")); //$NON-NLS-1$
		return area;
	}

	public static IPath[] chooseFileEntries(Shell shell,
			IPath initialSelection, IPath[] usedEntries, String title,
			String description, String[] fileExtensions, boolean allowMultiple,
			boolean allowDirectories, boolean allowFiles) {
		if (usedEntries == null) {
			throw new IllegalArgumentException("ddddd"); //$NON-NLS-1$
		}

		// List clazzes = new ArrayList();
		List<Class<?>> clazzes = new ArrayList<Class<?>>();
		if (allowDirectories) {
			clazzes.add(IFolder.class);
			clazzes.add(IProject.class);
		}
		if (allowFiles) {
			clazzes.add(IFile.class);
		}
		Class<?>[] acceptedClasses = (Class<?>[]) clazzes
				.toArray(new Class[clazzes.size()]);

		TypedElementSelectionValidator validator = new TypedElementSelectionValidator(
				acceptedClasses, true);
		List<IFile> usedFiles = new ArrayList<IFile>(usedEntries.length);
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		for (int i = 0; i < usedEntries.length; i++) {
			IResource resource = root.findMember(usedEntries[i]);
			if (resource instanceof IFile) {
				usedFiles.add((IFile) resource);
			}
		}
		IResource focus = initialSelection != null ? root
				.findMember(initialSelection) : null;

		ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(
				shell, new WorkbenchLabelProvider(),
				new WorkbenchContentProvider());
		dialog.setValidator(validator);
		dialog.setAllowMultiple(allowMultiple);
		dialog.setTitle(title);
		dialog.setMessage(description);
		dialog.addFilter(new FileFilter(fileExtensions, usedFiles, true,
				allowDirectories));
		dialog.setInput(root);
		dialog.setSorter(new ResourceSorter(ResourceSorter.NAME));
		dialog.setInitialSelection(focus);

		if (dialog.open() == Window.OK) {
			Object[] elements = dialog.getResult();
			IPath[] res = new IPath[elements.length];
			for (int i = 0; i < res.length; i++) {
				IResource elem = (IResource) elements[i];
				res[i] = elem.getFullPath();
			}
			return res;
		}
		return null;
	}

	protected String formatPkgName(String str) {
		int i = str.lastIndexOf("/"); //$NON-NLS-1$
		if (i >= 0) {
			str = str.substring(0, i);
			if (str.indexOf("\\") != -1) { //$NON-NLS-1$
				str = str.replaceAll("\\", "."); //$NON-NLS-1$ //$NON-NLS-2$
			} else if (str.indexOf("/") != -1) { //$NON-NLS-1$
				str = str.replace("/", "."); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
		return str;
	}

	/**
	 * Create contents of the button bar
	 * 
	 * @param parent
	 */
	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		createButton(parent, IDialogConstants.OK_ID, Messages.getString("CreateClassDialog.create"), true); //$NON-NLS-1$
		createButton(parent, IDialogConstants.CANCEL_ID, Messages.getString("CreateClassDialog.cancel"), false); //$NON-NLS-1$
		this.getButton(IDialogConstants.OK_ID).setEnabled(false);
	}

	/**
	 * Return the initial size of the dialog
	 */
	@Override
	protected Point getInitialSize() {
		return new Point(500, 375);
	}

	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText(Messages.getString("CreateClassDialog.createvalidateclass")); //$NON-NLS-1$
	}

	protected void buttonPressed(int buttonId) {
		if (buttonId == IDialogConstants.OK_ID) {
			Map<String, String> classInfo = new HashMap<String, String>();

			this.pkgName = this.pkgText.getText();
			this.className = this.classNameText.getText();

			classInfo.put("package", this.pkgName); //$NON-NLS-1$
			classInfo.put("name", this.className); //$NON-NLS-1$

			String srcNameTemp = this.srcName.replace("/", File.separator); //$NON-NLS-1$ //$NON-NLS-2$
			String projectName = this.projectName;

			String currFilePath = project.getLocation().toOSString();
			wokSpacePath = currFilePath.substring(0, currFilePath
					.indexOf(projectName));
			String targePath = wokSpacePath
					+ projectName
					+ File.separator
					+ srcNameTemp //$NON-NLS-1$
					+ File.separator
					+ this.pkgName.replace(".", File.separator) + File.separator; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
			String filePath = targePath + this.className + ".java"; //$NON-NLS-1$
			File classFile = new File(filePath);
			if (classFile.exists()) {
				if (MessageDialog.openConfirm(null, "", "")) { //$NON-NLS-1$ //$NON-NLS-2$

					generateFile(classInfo, projectName, targePath);
				}
			} else {
				generateFile(classInfo, projectName, targePath);
			}

		}
		super.buttonPressed(buttonId);
	}

	// 修改添加
	private void generateFile(Map<String, String> classInfo,
			String projectName, String targePath) {

		FreemarkerUtils.writeTemplateToFile("template/saturnvalidateClass.ftl", //$NON-NLS-1$
				classInfo, targePath + File.separator + classInfo.get("name") //$NON-NLS-1$
						+ ".java"); //$NON-NLS-1$

		SaturnProjectUtil.refreshProject(projectName);
	}

	private void dialogChanged() {
		if (SaturnValidation.isEmpty(getSrcText())) {
			setErrorMessage(Messages.getString("CreateClassDialog.srcfileurlcannotempty")); //$NON-NLS-1$
			return;
		}

		if (SaturnValidation.isEmpty(getPkgText())) {
			setErrorMessage(Messages.getString("CreateClassDialog.packageurlcannotempty")); //$NON-NLS-1$
			this.getButton(IDialogConstants.OK_ID).setEnabled(false);
			return;
		}

		if (SaturnValidation.isEmpty(getClassNameText())) {
			setErrorMessage(Messages.getString("CreateClassDialog.classnamecannotempty")); //$NON-NLS-1$
			this.getButton(IDialogConstants.OK_ID).setEnabled(false);
			return;
		}

		if (SaturnValidation.isHasDot(getClassNameText())) {
			setErrorMessage(Messages.getString("CreateClassDialog.classnamelimit"));  //$NON-NLS-1$
			this.getButton(IDialogConstants.OK_ID).setEnabled(false);
			return;
		}

		if (!SaturnValidation.isValidProgramStr(getClassNameText())) {
			setErrorMessage(Messages.getString("CreateClassDialog.classnameillegal")); //$NON-NLS-1$
			this.getButton(IDialogConstants.OK_ID).setEnabled(false);
			return;
		}

		if (!SaturnValidation.isPriUpper(getClassNameText())) {
			setErrorMessage(Messages.getString("CreateClassDialog.classnamemustbecapital")); //$NON-NLS-1$
			this.getButton(IDialogConstants.OK_ID).setEnabled(false);
			return;
		}
		
//		if (getClassNameText().trim().length()== 50) {
//			setErrorMessage(Messages.getString("CreateClassDialog.classnamelengthlimit")); //$NON-NLS-1$
//			return;
//		}

		setErrorMessage(null);

		this.getButton(IDialogConstants.OK_ID).setEnabled(true);
	}

	public String getClassNameText() {
		return classNameText.getText();
	}

	public String getPkgText() {
		return pkgText.getText();
	}

	public String getSrcText() {
		return srcText.getText();
	}

	public String getPkgName() {
		return pkgName;
	}

	public void setPkgName(String pkgName) {
		this.pkgName = pkgName;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

}
